#include "parse.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

void parse_xref( tstack_t *ts, FILE* stream, long id)
{
	//clear the output stream
	rewind(stream);
	ftruncate(fileno(stream),0);

	//invert the stack for forward
	//processing
	//tstack_t ts_inv = DEFAULT_TSTACK;
	//tstack_invert(&ts_inv,ts);


  if ( id )
    fprintf( stream, "%ld\n", id );

	xrefparser_t xp;
	xp.state = TAG_NONE;

	tag_t tag = DEFAULT_TAG;

  while ( tstack_pop( ts,&tag) )
	{
    if ( !strcmp(tag.name,"single-completion") )
    {
      if ( !tag.end )
        xp.state = TAG_SINGLECOMPL;
    }
    if ( !tag.end )
    {
      if ( !strcmp(tag.name,"position-lc")
          && xp.state != TAG_SINGLECOMPL /* ignore position move if single completion */
          )
      {
        char *file;
        int line, col;
        line = col = 0;
        //fprintf( stream, "position-lc %s\n", tag.tok.v );
        for ( int i =0; i < tag.nattrs; i++ )
        {
          //fprintf( stream, " %s=%s", tag.attrs[i].key, tag.attrs[i].val);
          if ( !strcmp( tag.attrs[i].key, "line" ) )
          {
            line = atoi(tag.attrs[i].val);
          }
          else if ( !strcmp( tag.attrs[i].key, "col" ) )
          {
            col = atoi(tag.attrs[i].val);
          }
        }
        file =  tag.tok.v;
        if ( col > 0 )
          fprintf( stream, "e %s | normal %dG0%dl", file, line, col );   
        else if ( col == 0 )
          fprintf( stream, "e %s | normal %dG0", file, line );   
        //fprintf(  stream, "\n" );
      }
      else if ( !strcmp(tag.name,"all-completions") 
          || !strcmp(tag.name,"single-completion") )
      {
       // fprintf( stream, "tok='%s'\n", tag.tok.v );
        char word[PARSE_COMPL_MAX_SIZE], subcmd[PARSE_COMPL_MAX_SIZE];
        char * pch;
        char * brk = "\n";
        str_t cmd = DEFAULT_STR;
        str_create(&cmd);

        str_cats( &cmd, "let res = [] " );

        pch = strtok (tag.tok.v,brk);
				int parse_compl_state = -1;
				bool newline = false;

				str_t info = DEFAULT_STR;
				str_create(&info);

        while (pch != NULL)
        {
					char *c,*d,t;
					c = pch;
					if (*c != ' ')
					{
						newline = true;
						if ( parse_compl_state != -1 )
						{
							//save the prev line
							sprintf( subcmd, " | call add(res, { \"word\": \"%s\", \"menu\": \"%s\", \"info\": \"%s\", \"dup\": \"1\"}) ",
									word, 
									info.v,
									info.v );
							str_cats( &cmd, subcmd );
							str_clear(&info); //clear the info
						}
						else
							parse_compl_state = 0;
					}
					else
					{
						newline = false;
					}

					if ( newline )
					{
						while(*c==' ') c++;
						d = c;
						while(*d!=' '&&*d!='\n'&&*d!='\0') d++;
						t=*d;
						*d='\0';
						strcpy(word,c);
						*d=t;

						//need to parse the rest
						char *c2, *d2;
						c2 = d;
						while(*c2==' '||*c2==':') c2++;
						d2 = c2;
						while(*d2!='\n'&&*d2!='\0') d2++;
						t=*d2;
						*d2='\0';
            for ( unsigned int i = 0; i < strlen(c2); i++ )
            {
              if ( c2[i] == '"' )
              {
                str_catc(&info,'\\');
                str_catc(&info,c2[i]);
              }
              else
              {
                str_catc(&info,c2[i]);
              }
            }
						*d2=t;
					}
					else
					{
						while(*c==' ') c++;
						d = c;
						while(*d!='\n'&&*d!='\0') d++;
						t=*d;
						*d='\0';
            for ( unsigned int i = 0; i < strlen(c); i++ )
            {
              if ( c[i] == '"' )
              {
                str_catc(&info,'\\');
                str_catc(&info,c[i]);
              }
              else
              {
                str_catc(&info,c[i]);
              }
            }
						*d=t;
					}

          pch = strtok (NULL,brk);
        }
				sprintf( subcmd, " | call add(res, { \"word\": \"%s\", \"menu\": \"%s\", \"info\": \"%s\", \"dup\": \"1\"}) ",
						word, 
						info.v,
						info.v );
				str_cats( &cmd, subcmd );

        fprintf( stream, "%s", cmd.v );
        str_free(&cmd);
				str_free(&info);
      }
      else if ( !strcmp(tag.name,"sync")  )
      {
        xp.state = TAG_SYNC;
      }
    }
    str_free( &tag.tok );
	}

	fflush(stream);

	//tstack_free(&ts_inv);
}
